<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
// $Id: Action.class.php 2702 2012-02-02 12:35:01Z liu21st $


/**
 +------------------------------------------------------------------------------
 * ThinkPHP Action控制器基类 精简模式
 +------------------------------------------------------------------------------
 * @category   Think
 * @package  Think
 * @subpackage  Core
 * @author   liu21st <liu21st@gmail.com>
 * @version  $Id: Action.class.php 2702 2012-02-02 12:35:01Z liu21st $
 +------------------------------------------------------------------------------
 */
abstract class Action {
	
	// 当前Action名称
	private $name = '';
	protected $tVar = array (); // 模板输出变量
	

	/**
     +----------------------------------------------------------
	 * 架构函数 取得模板对象实例
     +----------------------------------------------------------
	 * @access public
     +----------------------------------------------------------
	 */
	public function __construct() {
		tag ( 'action_begin' );
		//控制器初始化
		if (method_exists ( $this, '_initialize' ))
			$this->_initialize ();
	}
	
	/**
     +----------------------------------------------------------
	 * 获取当前Action名称
     +----------------------------------------------------------
	 * @access protected
     +----------------------------------------------------------
	 */
	protected function getActionName() {
		if (empty ( $this->name )) {
			// 获取Action名称
			$this->name = substr ( get_class ( $this ), 0, - 6 );
		}
		return $this->name;
	}
	
	/**
     +----------------------------------------------------------
	 * 是否AJAX请求
     +----------------------------------------------------------
	 * @access protected
     +----------------------------------------------------------
	 * @return bool
     +----------------------------------------------------------
	 */
	protected function isAjax() {
		if (isset ( $_SERVER ['HTTP_X_REQUESTED_WITH'] )) {
			if ('xmlhttprequest' == strtolower ( $_SERVER ['HTTP_X_REQUESTED_WITH'] ))
				return true;
		}
		if (! empty ( $_POST [C ( 'VAR_AJAX_SUBMIT' )] ) || ! empty ( $_GET [C ( 'VAR_AJAX_SUBMIT' )] ))
			// 判断Ajax方式提交
			return true;
		return false;
	}
	
	/**
     +----------------------------------------------------------
	 * 模板变量赋值
     +----------------------------------------------------------
	 * @access public
     +----------------------------------------------------------
	 * @param mixed $name
	 * @param mixed $value
     +----------------------------------------------------------
	 */
	public function assign($name, $value = '') {
		if (is_array ( $name )) {
			$this->tVar = array_merge ( $this->tVar, $name );
		} elseif (is_object ( $name )) {
			foreach ( $name as $key => $val )
				$this->tVar [$key] = $val;
		} else {
			$this->tVar [$name] = $value;
		}
	}
	
	public function __set($name, $value) {
		$this->assign ( $name, $value );
	}
	
	/**
     +----------------------------------------------------------
	 * 取得模板变量的值
     +----------------------------------------------------------
	 * @access public
     +----------------------------------------------------------
	 * @param string $name
     +----------------------------------------------------------
	 * @return mixed
     +----------------------------------------------------------
	 */
	public function get($name) {
		if (isset ( $this->tVar [$name] ))
			return $this->tVar [$name];
		else
			return false;
	}
	
	/**
     +----------------------------------------------------------
	 * 魔术方法 有不存在的操作的时候执行
     +----------------------------------------------------------
	 * @access public
     +----------------------------------------------------------
	 * @param string $method 方法名
	 * @param array $args 参数
     +----------------------------------------------------------
	 * @return mixed
     +----------------------------------------------------------
	 */
	public function __call($method, $args) {
		if (0 === strcasecmp ( $method, ACTION_NAME )) {
			if (method_exists ( $this, '_empty' )) {
				// 如果定义了_empty操作 则调用
				$this->_empty ( $method, $args );
			} elseif (file_exists_case ( C ( 'TEMPLATE_NAME' ) )) {
				// 检查是否存在默认模版 如果有直接输出模版
				$this->display ();
			} else {
				// 抛出异常
				throw_exception ( L ( '_ERROR_ACTION_' ) . ACTION_NAME );
			}
		} else {
			switch (strtolower ( $method )) {
				// 判断提交方式
				case 'ispost' :
				case 'isget' :
				case 'ishead' :
				case 'isdelete' :
				case 'isput' :
					return strtolower ( $_SERVER ['REQUEST_METHOD'] ) == strtolower ( substr ( $method, 2 ) );
				// 获取变量 支持过滤和默认值 调用方式 $this->_post($key,$filter,$default);
				case '_get' :
					$input = & $_GET;
					break;
				case '_post' :
					$input = & $_POST;
					break;
				case '_put' :
					parse_str ( file_get_contents ( 'php://input' ), $input );
					break;
				case '_request' :
					$input = & $_REQUEST;
					break;
				case '_session' :
					$input = & $_SESSION;
					break;
				case '_cookie' :
					$input = & $_COOKIE;
					break;
				case '_server' :
					$input = & $_SERVER;
					break;
				case '_globals' :
					$input = & $GLOBALS;
					break;
				default :
					throw_exception ( __CLASS__ . ':' . $method . L ( '_METHOD_NOT_EXIST_' ) );
			}
			if (isset ( $input [$args [0]] )) { // 取值操作
				$data = $input [$args [0]];
				$fun = $args [1] ? $args [1] : C ( 'DEFAULT_FILTER' );
				$data = $fun ( $data ); // 参数过滤
			} else { // 变量默认值
				$data = isset ( $args [2] ) ? $args [2] : NULL;
			}
			return $data;
		}
	}
	
	/**
     +----------------------------------------------------------
	 * 操作错误跳转的快捷方法
     +----------------------------------------------------------
	 * @access protected
     +----------------------------------------------------------
	 * @param string $message 错误信息
	 * @param string $jumpUrl 页面跳转地址
	 * @param Boolean $ajax 是否为Ajax方式
     +----------------------------------------------------------
	 * @return void
     +----------------------------------------------------------
	 */
	protected function error($message, $jumpUrl = '', $ajax = false) {
		$this->dispatchJump ( $message, 0, $jumpUrl, $ajax );
	}
	
	/**
     +----------------------------------------------------------
	 * 操作成功跳转的快捷方法
     +----------------------------------------------------------
	 * @access protected
     +----------------------------------------------------------
	 * @param string $message 提示信息
	 * @param string $jumpUrl 页面跳转地址
	 * @param Boolean $ajax 是否为Ajax方式
     +----------------------------------------------------------
	 * @return void
     +----------------------------------------------------------
	 */
	protected function success($message, $jumpUrl = '', $ajax = false) {
		$this->dispatchJump ( $message, 1, $jumpUrl, $ajax );
	}
	
	/**
     +----------------------------------------------------------
	 * Ajax方式返回数据到客户端
     +----------------------------------------------------------
	 * @access protected
     +----------------------------------------------------------
	 * @param mixed $data 要返回的数据
	 * @param String $info 提示信息
	 * @param boolean $status 返回状态
	 * @param String $status ajax返回类型 JSON XML
     +----------------------------------------------------------
	 * @return void
     +----------------------------------------------------------
	 */
	protected function ajaxReturn($data, $info = '', $status = 1, $type = '') {
		$result = array ();
		$result ['status'] = $status;
		$result ['info'] = $info;
		$result ['data'] = $data;
		//扩展ajax返回数据, 在Action中定义function ajaxAssign(&$result){} 方法 扩展ajax返回数据。
		if (method_exists ( $this, "ajaxAssign" ))
			$this->ajaxAssign ( $result );
		if (empty ( $type ))
			$type = C ( 'DEFAULT_AJAX_RETURN' );
		if (strtoupper ( $type ) == 'JSON') {
			// 返回JSON数据格式到客户端 包含状态信息
			header ( "Content-Type:text/html; charset=utf-8" );
			exit ( json_encode ( $result ) );
		} elseif (strtoupper ( $type ) == 'XML') {
			// 返回xml格式数据
			header ( "Content-Type:text/xml; charset=utf-8" );
			exit ( xml_encode ( $result ) );
		}
	}
	
	/**
     +----------------------------------------------------------
	 * Action跳转(URL重定向） 支持指定模块和延时跳转
     +----------------------------------------------------------
	 * @access protected
     +----------------------------------------------------------
	 * @param string $url 跳转的URL表达式
	 * @param array $params 其它URL参数
	 * @param integer $delay 延时跳转的时间 单位为秒
	 * @param string $msg 跳转提示信息
     +----------------------------------------------------------
	 * @return void
     +----------------------------------------------------------
	 */
	protected function redirect($url, $params = array(), $delay = 0, $msg = '') {
		$url = U ( $url, $params );
		redirect ( $url, $delay, $msg );
	}
	
	/**
     +----------------------------------------------------------
	 * 默认跳转操作 支持错误导向和正确跳转
	 * 调用模板显示 默认为public目录下面的success页面
	 * 提示页面为可配置 支持模板标签
     +----------------------------------------------------------
	 * @param string $message 提示信息
	 * @param Boolean $status 状态
	 * @param string $jumpUrl 页面跳转地址
	 * @param Boolean $ajax 是否为Ajax方式
     +----------------------------------------------------------
	 * @access private
     +----------------------------------------------------------
	 * @return void
     +----------------------------------------------------------
	 */
	private function dispatchJump($message, $status = 1, $jumpUrl = '', $ajax = false) {
		// 判断是否为AJAX返回
		if ($ajax || $this->isAjax ())
			$this->ajaxReturn ( $ajax, $message, $status );
		if (! empty ( $jumpUrl ))
			$this->assign ( 'jumpUrl', $jumpUrl );
		
		// 提示标题
		$this->assign ( 'msgTitle', $status ? L ( '_OPERATION_SUCCESS_' ) : L ( '_OPERATION_FAIL_' ) );
		//如果设置了关闭窗口，则提示完毕后自动关闭窗口
		if ($this->get ( 'closeWin' ))
			$this->assign ( 'jumpUrl', 'javascript:window.close();' );
		$this->assign ( 'status', $status ); // 状态
		//保证输出不受静态缓存影响
		C ( 'HTML_CACHE_ON', false );
		if ($status) { //发送成功信息
			$this->assign ( 'message', $message ); // 提示信息
			// 成功操作后默认停留1秒
			if (! $this->get ( 'waitSecond' ))
				$this->assign ( 'waitSecond', "1" );
			
		// 默认操作成功自动返回操作前页面
			if (! $this->get ( 'jumpUrl' ))
				$this->assign ( "jumpUrl", $_SERVER ["HTTP_REFERER"] );
			$this->display ( C ( 'TMPL_ACTION_SUCCESS' ) );
		} else {
			$this->assign ( 'error', $message ); // 提示信息
			//发生错误时候默认停留3秒
			if (! $this->get ( 'waitSecond' ))
				$this->assign ( 'waitSecond', "3" );
			
		// 默认发生错误的话自动返回上页
			if (! $this->get ( 'jumpUrl' ))
				$this->assign ( 'jumpUrl', "javascript:history.back(-1);" );
			$this->display ( C ( 'TMPL_ACTION_ERROR' ) );
			// 中止执行  避免出错后继续执行
			exit ();
		}
	}
	
	/**
     +----------------------------------------------------------
	 * 加载模板和页面输出 可以返回输出内容
     +----------------------------------------------------------
	 * @access public
     +----------------------------------------------------------
	 * @param string $templateFile 模板文件名
	 * @param string $charset 模板输出字符集
	 * @param string $contentType 输出类型
     +----------------------------------------------------------
	 * @return mixed
     +----------------------------------------------------------
	 */
	public function display($templateFile = '', $charset = '', $contentType = '') {
		G ( 'viewStartTime' );
		// 视图开始标签
		tag ( 'view_begin', $templateFile );
		// 解析并获取模板内容
		$content = $this->fetch ( $templateFile );
		// 输出模板内容
		$this->show ( $content, $charset, $contentType );
		// 视图结束标签
		tag ( 'view_end' );
	}
	
	/**
     +----------------------------------------------------------
	 * 输出内容文本可以包括Html
     +----------------------------------------------------------
	 * @access public
     +----------------------------------------------------------
	 * @param string $content 输出内容
	 * @param string $charset 模板输出字符集
	 * @param string $contentType 输出类型
     +----------------------------------------------------------
	 * @return mixed
     +----------------------------------------------------------
	 */
	public function show($content, $charset = '', $contentType = '') {
		if (empty ( $charset ))
			$charset = C ( 'DEFAULT_CHARSET' );
		if (empty ( $contentType ))
			$contentType = C ( 'TMPL_CONTENT_TYPE' );
		
		// 网页字符编码
		header ( "Content-Type:" . $contentType . "; charset=" . $charset );
		header ( "Cache-control: private" ); //支持页面回跳
		header ( "X-Powered-By:TOPThink/" . THINK_VERSION );
		// 输出模板文件
		echo $content;
	}
	
	/**
     +----------------------------------------------------------
	 * 解析和获取模板内容 用于输出
     +----------------------------------------------------------
	 * @access public
     +----------------------------------------------------------
	 * @param string $templateFile 模板文件名
     +----------------------------------------------------------
	 * @return string
     +----------------------------------------------------------
	 */
	public function fetch($templateFile = '') {
		// 模板文件解析标签
		tag ( 'view_template', $templateFile );
		// 模板文件不存在直接返回
		if (! is_file ( $templateFile ))
			return NULL;
		
		// 页面缓存
		ob_start ();
		ob_implicit_flush ( 0 );
		// 视图解析标签
		$params = array ('var' => $this->tVar, 'file' => $templateFile );
		$result = tag ( 'view_parse', $params );
		if (false === $result) { // 未定义行为 则采用PHP原生模板
			// 模板阵列变量分解成为独立变量
			extract ( $this->tVar, EXTR_OVERWRITE );
			// 直接载入PHP模板
			include $templateFile;
		}
		// 获取并清空缓存
		$content = ob_get_clean ();
		// 内容过滤标签
		tag ( 'view_filter', $content );
		// 输出模板文件
		return $content;
	}
	
	/**
     +----------------------------------------------------------
	 * 析构方法
     +----------------------------------------------------------
	 * @access public
     +----------------------------------------------------------
	 */
	public function __destruct() {
		// 保存日志
		if (C ( 'LOG_RECORD' ))
			Log::save ();
		
		// 执行后续操作
		tag ( 'action_end' );
	}
}